/*     */ package com.zimbra.cs.service.admin;
/*     */ 
/*     */ import com.zimbra.common.auth.ZAuthToken;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.AdminConstants;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.MapUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.AuthToken;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.Server;
/*     */ import com.zimbra.cs.account.accesscontrol.AdminRight;
/*     */ import com.zimbra.cs.account.accesscontrol.Rights.Admin;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.service.FileUploadServlet;
/*     */ import com.zimbra.cs.service.FileUploadServlet.Upload;
/*     */ import com.zimbra.cs.util.WebClientServiceUtil;
/*     */ import com.zimbra.cs.zimlet.ZimletDescription;
/*     */ import com.zimbra.cs.zimlet.ZimletException;
/*     */ import com.zimbra.cs.zimlet.ZimletFile;
/*     */ import com.zimbra.cs.zimlet.ZimletUtil;
/*     */ import com.zimbra.cs.zimlet.ZimletUtil.DeployListener;
/*     */ import com.zimbra.cs.zimlet.ZimletUtil.ZimletSoapUtil;
/*     */ import com.zimbra.soap.ZimbraSoapContext;
/*     */ import java.io.IOException;
/*     */ import java.util.HashMap;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Map.Entry;
/*     */ import java.util.concurrent.CountDownLatch;
/*     */ import java.util.concurrent.TimeUnit;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class DeployZimlet
/*     */   extends AdminDocumentHandler
/*     */ {
/*     */   public static final String sPENDING = "pending";
/*     */   public static final String sSUCCEEDED = "succeeded";
/*     */   public static final String sFAILED = "failed";
/*     */   private Map<String, Progress> mProgressMap;
/*     */   
/*     */   private static class Progress
/*     */     implements ZimletUtil.DeployListener
/*     */   {
/*     */     private Map<String, Status> mStatus;
/*     */     
/*     */     public Progress(boolean allServers)
/*     */       throws ServiceException
/*     */     {
/*  66 */       this.mStatus = new HashMap();
/*  67 */       Provisioning prov = Provisioning.getInstance();
/*  68 */       if (!allServers) {
/*  69 */         changeStatus(prov.getLocalServer().getName(), "pending");
/*  70 */         return;
/*     */       }
/*  72 */       for (Server s : prov.getAllServers()) {
/*  73 */         changeStatus(s.getName(), "pending");
/*     */       }
/*     */     }
/*     */     
/*     */     public void markFinished(Server s)
/*     */     {
/*  79 */       changeStatus(s.getName(), "succeeded");
/*     */     }
/*     */     
/*     */     public void markFailed(Server s, Exception e)
/*     */     {
/*  84 */       changeStatus(s.getName(), "failed");
/*  85 */       ((Status)this.mStatus.get(s.getName())).error = e;
/*     */     }
/*     */     
/*     */     public void changeStatus(String name, String status) {
/*  89 */       Status s = (Status)this.mStatus.get(name);
/*  90 */       if (s == null) {
/*  91 */         s = new Status(null);
/*  92 */         this.mStatus.put(name, s);
/*     */       }
/*  94 */       s.value = status;
/*     */     }
/*     */     
/*     */     public void writeResponse(Element resp) {
/*  98 */       for (Map.Entry<String, Status> entry : this.mStatus.entrySet()) {
/*  99 */         Element progress = resp.addElement("progress");
/* 100 */         progress.addAttribute("server", (String)entry.getKey());
/* 101 */         progress.addAttribute("status", ((Status)entry.getValue()).value);
/* 102 */         Exception e = ((Status)entry.getValue()).error;
/* 103 */         if (e != null)
/* 104 */           progress.addAttribute("error", e.getMessage());
/*     */       }
/*     */     }
/*     */     
/*     */     private static class Status { String value;
/*     */       Exception error; } }
/*     */   
/*     */   private static class DeployThread implements Runnable { final Server server;
/*     */     DeployZimlet.Progress progress;
/*     */     ZAuthToken auth;
/*     */     boolean flushCache;
/* 115 */     boolean isLocal = true;
/*     */     ZimletFile zf;
/*     */     
/*     */     public DeployThread(Server server, DeployZimlet.Progress pr, ZAuthToken au, boolean flush, ZimletFile zf) {
/* 119 */       this.server = server;
/* 120 */       this.progress = pr;
/* 121 */       this.zf = zf;
/* 122 */       if (au != null) {
/* 123 */         this.auth = au;
/* 124 */         this.isLocal = false;
/*     */       }
/* 126 */       this.flushCache = flush;
/*     */     }
/*     */     
/*     */     public void run()
/*     */     {
/*     */       try {
/* 132 */         if (this.isLocal) {
/* 133 */           ZimletUtil.deployZimletLocally(this.zf, this.progress);
/*     */         } else {
/* 135 */           byte[] data = this.zf.toByteArray();
/* 136 */           ZimletUtil.ZimletSoapUtil soapUtil = new ZimletUtil.ZimletSoapUtil(this.auth);
/* 137 */           soapUtil.deployZimletRemotely(this.server, this.zf.getName(), data, this.progress, this.flushCache);
/*     */         }
/*     */       } catch (Exception e) {
/* 140 */         if (this.server != null) {
/* 141 */           ZimbraLog.zimlet.warn("failed to deploy zimlet on node %s", this.server.getName(), e);
/*     */         } else {
/* 143 */           ZimbraLog.zimlet.warn("failed to get local server", e);
/*     */         }
/* 145 */         if ((this.server != null) && (this.progress != null)) {
/* 146 */           this.progress.markFailed(this.server, e);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public DeployZimlet()
/*     */   {
/* 154 */     this.mProgressMap = MapUtil.newLruMap(20);
/*     */   }
/*     */   
/*     */   private void deploy(ZimbraSoapContext lc, Server server, ZimletFile zf, String aid, ZAuthToken auth, boolean flushCache, boolean synchronous, CountDownLatch latch) throws ServiceException
/*     */   {
/* 159 */     Progress pr = new Progress(auth != null);
/* 160 */     this.mProgressMap.put(aid, pr);
/*     */     
/* 162 */     Runnable action = new DeployThread(server, pr, auth, flushCache, zf);
/* 163 */     Thread t = new Thread(action);
/* 164 */     t.start();
/* 165 */     if (!synchronous) {
/*     */       try {
/* 167 */         t.join(TimeUnit.MILLISECONDS.convert(LC.zimlet_deploy_timeout.intValue(), TimeUnit.SECONDS));
/*     */       } catch (InterruptedException e) {
/* 169 */         ZimbraLog.zimlet.warn("error deploying Zimlet", e);
/*     */       }
/*     */     }
/* 172 */     if (latch != null) {
/* 173 */       latch.countDown();
/*     */     }
/*     */   }
/*     */   
/*     */   public Element handle(Element request, Map<String, Object> context) throws ServiceException
/*     */   {
/* 179 */     ZimbraSoapContext zsc = getZimbraSoapContext(context);
/* 180 */     String action = request.getAttribute("action").toLowerCase();
/* 181 */     Element content = request.getElement("content");
/* 182 */     String aid = content.getAttribute("aid", null);
/* 183 */     if ((aid == null) || (aid.isEmpty())) {
/* 184 */       throw MailServiceException.INVALID_REQUEST("Missing or invalid upload id (aid)", null);
/*     */     }
/* 186 */     boolean flushCache = request.getAttributeBool("flush", false);
/* 187 */     boolean synchronous = request.getAttributeBool("synchronous", false);
/* 188 */     if (!"status".equals(action))
/*     */     {
/* 190 */       if (("deployall".equals(action)) || ("deploylocal".equals(action)))
/*     */       {
/* 192 */         FileUploadServlet.Upload up = FileUploadServlet.fetchUpload(zsc.getAuthtokenAccountId(), aid, zsc.getAuthToken());
/* 193 */         if (up == null) {
/* 194 */           throw MailServiceException.NO_SUCH_UPLOAD(aid);
/*     */         }
/*     */         ZimletFile zf;
/*     */         try {
/* 198 */           zf = new ZimletFile(up.getName(), up.getInputStream());
/* 199 */           if ((zf.getZimletDescription().isExtension()) && (!zsc.getAuthToken().isAdmin())) {
/* 200 */             throw ServiceException.PERM_DENIED("Only global admin is allowed to deploy extensions for Zimbra Admin UI");
/*     */           }
/*     */           
/* 203 */           if (!zf.getZimletName().matches("^[\\w.-]+$")) {
/* 204 */             throw ZimletException.INVALID_ZIMLET_NAME();
/*     */           }
/*     */         } catch (IOException|ZimletException e1) {
/* 207 */           ZimbraLog.zimlet.warn("error deploying Zimlet", e1);
/* 208 */           throw ServiceException.FAILURE("error deploying Zimlet", e1);
/*     */         }
/* 210 */         if ("deployall".equals(action)) {
/* 211 */           List<Server> servers = Provisioning.getInstance().getAllServers();
/*     */           
/* 213 */           CountDownLatch latch = new CountDownLatch(servers.size());
/* 214 */           ZimbraLog.zimlet.debug("countdown latch init: %d", new Object[] { Long.valueOf(latch.getCount()) });
/* 215 */           for (Server server : servers) {
/*     */             try {
/* 217 */               checkRight(zsc, context, server, Rights.Admin.R_deployZimlet);
/* 218 */               ZimbraLog.zimlet.debug("countdown latch: %d", new Object[] { Long.valueOf(latch.getCount()) });
/*     */               
/* 220 */               if (server.isLocalServer()) {
/* 221 */                 deploy(zsc, server, zf, aid, null, false, synchronous, latch);
/*     */               } else {
/* 223 */                 ZimbraLog.zimlet.info("deploy on remote node %s", new Object[] { server.getName() });
/* 224 */                 deploy(zsc, server, zf, aid, zsc.getRawAuthToken(), flushCache, synchronous, latch);
/*     */               }
/* 226 */               if (flushCache) {
/* 227 */                 if (ZimbraLog.misc.isDebugEnabled()) {
/* 228 */                   ZimbraLog.misc.debug("DeployZimlet: flushing zimlet cache");
/*     */                 }
/* 230 */                 checkRight(zsc, context, Provisioning.getInstance().getLocalServer(), Rights.Admin.R_flushCache);
/* 231 */                 if (server.hasMailClientService()) {
/* 232 */                   FlushCache.flushAllZimlets(context);
/*     */                 } else {
/* 234 */                   WebClientServiceUtil.sendFlushZimletRequestToUiNode(server);
/*     */                 }
/*     */               }
/*     */             } catch (ServiceException e) {
/* 238 */               latch.countDown();
/* 239 */               ZimbraLog.zimlet.warn("deploy zimlet failed for node %s, coutdown latch %d", server.getName(), Long.valueOf(latch.getCount()), e);
/*     */             }
/*     */           }
/*     */           try
/*     */           {
/* 244 */             latch.await(LC.zimlet_deploy_timeout.intValue() * servers.size(), TimeUnit.SECONDS);
/*     */           } catch (InterruptedException e) {
/* 246 */             ZimbraLog.zimlet.warn("CountDownLatch failed %d", Long.valueOf(latch.getCount()), e);
/*     */           }
/* 248 */           FileUploadServlet.deleteUpload(up);
/* 249 */         } else if ("deploylocal".equals(action)) {
/* 250 */           Server localServer = Provisioning.getInstance().getLocalServer();
/* 251 */           checkRight(zsc, context, localServer, Rights.Admin.R_deployZimlet);
/*     */           try {
/* 253 */             deploy(zsc, localServer, zf, aid, null, false, synchronous, null);
/*     */           } finally {
/* 255 */             FileUploadServlet.deleteUpload(up);
/*     */           }
/* 257 */           if (flushCache) {
/* 258 */             if (ZimbraLog.misc.isDebugEnabled()) {
/* 259 */               ZimbraLog.misc.debug("DeployZimlet: flushing zimlet cache");
/*     */             }
/* 261 */             checkRight(zsc, context, localServer, Rights.Admin.R_flushCache);
/* 262 */             if (localServer.hasMailClientService()) {
/* 263 */               FlushCache.flushAllZimlets(context);
/*     */             } else {
/* 265 */               WebClientServiceUtil.sendFlushZimletRequestToUiNode(localServer);
/*     */             }
/*     */           }
/*     */         }
/*     */       } else {
/* 270 */         throw ServiceException.INVALID_REQUEST("invalid action " + action, null);
/*     */       }
/*     */     }
/* 273 */     Element response = zsc.createElement(AdminConstants.DEPLOY_ZIMLET_RESPONSE);
/* 274 */     Progress progress = (Progress)this.mProgressMap.get(aid);
/* 275 */     if (progress != null) {
/* 276 */       progress.writeResponse(response);
/*     */     }
/* 278 */     return response;
/*     */   }
/*     */   
/*     */   public void docRights(List<AdminRight> relatedRights, List<String> notes)
/*     */   {
/* 283 */     relatedRights.add(Rights.Admin.R_deployZimlet);
/*     */     
/* 285 */     notes.add("If deploying on all servers, need the " + Rights.Admin.R_deployZimlet.getName() + " right on all servers or on global grant.  If deploying on local server, need " + "the " + Rights.Admin.R_deployZimlet.getName() + " on the local server. Only global admin is allowed to deploy extensions to Zimbra Admin UI.");
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/admin/DeployZimlet.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */